package com.itheima.reggie.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.reggie.entity.*;
import com.itheima.reggie.entity.dto.OrderDto;
import com.itheima.reggie.entity.dto.OrderPageDto;
import com.itheima.reggie.mapper.OrderMapper;
import com.itheima.reggie.service.*;
import com.itheima.reggie.utils.ThreadLocalUtil;
import com.itheima.reggie.web.R;
import com.itheima.reggie.web.exception.BusinessException;
import com.sun.org.apache.xpath.internal.operations.Or;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
@Transactional
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {


    @Autowired
    AddressBookService addressBookService;

    @Autowired
    ShoppingCartService shoppingCartService;

    @Autowired
    OrderDetailService orderDetailService;

    @Autowired
    EmployeeService employeeService;

    /**
     * 提交订单。订单详情需要从数据库查询出来。
     *
     * @param order 订单的地址id、付款方式、备注
     * @return 是否下单成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R submit(Order order) {
        // 获取userId
        Long userId = ThreadLocalUtil.getCurrentId();

        // 查询购物车
        List<ShoppingCart> shoppingCarts = shoppingCartService.list(Wrappers.lambdaQuery(ShoppingCart.class).eq(ShoppingCart::getUserId, userId));

        if (ObjectUtils.isEmpty(shoppingCarts)) {
            throw new BusinessException("购物车为空，下单失败！");
        }

        // 计算订单总价
        int totalAmount = shoppingCarts.stream().mapToInt(sc -> sc.getAmount() * sc.getNumber()).reduce(Integer::sum).orElse(0);


        // 根据地址id，查询地址详情
        AddressBook ab = addressBookService.getById(order.getAddressBookId());

        // 组装订单基本信息
        order.setOrderTime(LocalDateTime.now());
        order.setCheckoutTime(LocalDateTime.now());
        order.setUserId(userId);
        order.setAmount(BigDecimal.valueOf(totalAmount));
        order.setStatus(2); // 默认已经付款了

        order.setConsignee(ab.getConsignee());
        order.setPhone(ab.getPhone());
        order.setAddress(ab.getDetail());


        // 保存基本信息
        if (!save(order)) {
            throw new BusinessException("下单失败！");
        }


        Long orderId = order.getId();

        // 组装订单详情(shoppingCart->OrderDetail)
        List<OrderDetail> orderDetails = shoppingCarts.stream().map(sc -> {

            // 创建订单详情对象
            OrderDetail orderDetail = new OrderDetail();
            // 赋值相同属性
            BeanUtils.copyProperties(sc, orderDetail, "id", "amount");

            // 手动设置不同属性
            orderDetail.setOrderId(orderId);
            orderDetail.setAmount(BigDecimal.valueOf(sc.getAmount())); // 订单中每个商品的价格

            return orderDetail;
        }).collect(Collectors.toList());


        // 保存订单详情
        orderDetailService.saveBatch(orderDetails);

        // 清空购物车
        shoppingCartService.remove(Wrappers.lambdaQuery(ShoppingCart.class).eq(ShoppingCart::getUserId, userId));

        return R.success("下单成功", null);
    }

    /**
     * 分页查询订单（包含的订单详情）
     *
     * @param orderPageDto 分页条件和查询条件
     * @return 符合要求的分页数据
     */
    @Override
    public R<Page<OrderDto>> pageWithOrderDetails(OrderPageDto orderPageDto) {
        String name = orderPageDto.getName();
        Long number = orderPageDto.getNumber();
        String beginTime = orderPageDto.getBeginTime();
        String endTime = orderPageDto.getEndTime();


        // 获取用户id
        Long userId = ThreadLocalUtil.getCurrentId();

        // 判断是员工还是C端用户
        Employee employee = employeeService.getById(userId);


        // 调用service分页查询订单
        LambdaQueryWrapper<Order> qw = Wrappers.lambdaQuery(Order.class)
                .eq(ObjectUtils.isEmpty(employee), Order::getUserId, userId)
                .orderByDesc(Order::getOrderTime)
                .eq(StringUtils.isNotBlank(name), Order::getUserName, name)
                .like(number != null, Order::getId, number)
                .gt(!ObjectUtils.isEmpty(beginTime), Order::getOrderTime, beginTime)
                .lt(!ObjectUtils.isEmpty(endTime), Order::getOrderTime, endTime);

        Page<Order> pageResult = page(
                new Page<>(orderPageDto.getPage(), orderPageDto.getPageSize()),
                qw
        );

        // 汇总订单id
        List<Order> records = pageResult.getRecords();
        if (ObjectUtils.isEmpty(records)) {
            throw new BusinessException("查无订单！");
        }

        List<Long> orderIds = records.stream().map(order -> order.getId()).collect(Collectors.toList());

        // 处理订单号
        for (Order order : records) {
            if (order.getNumber() == null) {
                order.setNumber(order.getId() + "");
            }
        }

        // 查询所有订单详情
        List<OrderDetail> orderDetails = orderDetailService.list(Wrappers.lambdaQuery(OrderDetail.class).in(OrderDetail::getOrderId, orderIds));
        if (ObjectUtils.isEmpty(orderDetails)) {
            throw new BusinessException("该订单为空单！");
        }

        // 组织响应数据
        Page<OrderDto> orderDtoPage = new Page<>();
        BeanUtils.copyProperties(pageResult, orderDtoPage, "records");
        List<OrderDto> dtoRecords = records.stream().map(order -> {
            OrderDto orderDto = new OrderDto();
            BeanUtils.copyProperties(order, orderDto);

            Long orderId = order.getId();
            List<OrderDetail> ods = orderDetails.stream().filter(od -> od.getOrderId().equals(orderId)).collect(Collectors.toList());
            orderDto.setOrderDetails(ods);
            return orderDto;
        }).collect(Collectors.toList());

        orderDtoPage.setRecords(dtoRecords);

        // 组织数据并返回
        return R.success(orderDtoPage);
    }
}
